﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LoA.Shared.Physics;
using Microsoft.Xna.Framework;

namespace LoA.PhysicsEngine {
	public partial class PhysicsComponent : DrawableGameComponent {
		public override void Update(GameTime gameTime) {
			foreach (var itemA in objects) {
				List<IPhysicalBody> hited = new List<IPhysicalBody>( );
				foreach (var itemB in objects) {
					if (itemA != itemB) {
						if (itemA.Intersects(itemB)) {
							// Set information about colision objects
							hited.Add(itemA);
							hited.Add(itemB);

							// Get the vector between their centers
							Vector3 delta = itemB.BodyState.Position - itemA.BodyState.Position;

							// Calculate the point halfway between the spheres
							Vector3 center = itemA.BodyState.Position + delta / 2f;

							// Normalize the delta vector
							delta.Normalize( );

							// Move the spheres to resolve the collision
							itemA.CorrectPosition(this, center - delta * itemA.BodyModel.Radius);
							itemB.CorrectPosition(this, center + delta * itemB.BodyModel.Radius);

							// Get diff of powers
							var forceDelta = itemB.BodyState.Force - itemA.BodyState.Force;

							// Calculate the half diff of powers
							var forceMiddle = forceDelta / 1.5f;

							//// Odwrócenie wartości sił obiektów
							itemA.CorrectForce(this, itemA.BodyState.Force + forceMiddle);
							itemB.CorrectForce(this, itemB.BodyState.Force - forceMiddle);

							// Reflect the velocities to bounce the spheres
							// Korekcja zwrotu siły obiektów
							var reflectedA = Vector3.Reflect(itemA.BodyState.Velocity, delta);
							if (reflectedA.Length( ) > 0) {
								itemA.CorrectDirection(this, Vector3.Normalize(reflectedA));
							}

							var reflectedB = Vector3.Reflect(itemB.BodyState.Velocity, delta);
							if (reflectedB.Length( ) > 0) {
								itemB.CorrectDirection(this, Vector3.Normalize(reflectedB));
							}
						}
					}
				}
				if (!hited.Contains(itemA)) {
					// Animacja ruchu obiektu
					itemA.CorrectPosition(this, itemA.BodyState.Position + itemA.BodyState.Velocity * (float)gameTime.ElapsedGameTime.TotalSeconds);
					// Obniżenie siły w czasie
					itemA.CorrectForce(this, itemA.BodyState.Force - itemA.BodyState.Force * (float)Math.Pow(gameTime.ElapsedGameTime.TotalSeconds, 2));
					if (itemA.BodyState.Gravitation == GravitationState.Tendency) {
						// Wyzerowanie współrzędnej wysokości wektora zwrotu siły
						itemA.CorrectDirection(this, itemA.BodyState.Direction - new Vector3(0, itemA.BodyState.Direction.Y, 0));
						if (itemA.BodyState.Position.Y - itemA.BodyModel.Radius / 2.0f > 0)
							// Spadek swobodny
							itemA.CorrectPosition(this, itemA.BodyState.Position + (float)Math.Pow(Physics.Gn * (float)gameTime.ElapsedGameTime.TotalSeconds, 2) / 2.0f * Vector3.Down);
					}
				}

				itemA.Update(gameTime);
			}

			base.Update(gameTime);
		}
	}
}
